package filewriting;

import guiobjects.Observation;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;

import user.data.Data;

import commonfunctions.Matrix;



/**
 * creates an output file based on the predicted path. Draws the observations in real time, drawing black
 * lines for true negatives, red for true positives, blue for false negatives, green for false positives.
 * 
 * @author Trevor Terris
 *
 */
public class PathDisplayWriter 
{
	public static final String TRACKED_DATA_FILENAME = "tracked_objects.txt";
	
	public static Thread startWriting(ArrayList<Observation> obs, Matrix weights, Matrix tracks, String dir)
	{
		Thread toReturn = new WritingThread(obs, weights, tracks, dir);
		toReturn.start();
		return toReturn;
	}
	
	private static class WritingThread extends Thread
	{
		private ArrayList<Observation> myObservations;
		private Matrix myWeights;
		private Matrix myTracks;
		private String myDirName;
		private int myFrameRate = Data.pathDisplayFramerate;
		public WritingThread(ArrayList<Observation> obs, Matrix weights, Matrix tracks, String dir)
		{
			myObservations = obs;
			myWeights = weights;
			myTracks = tracks;
			myDirName = dir;
		}
		public void run()
		{
			try
			{
				myTracks = new Matrix(myTracks);
				ArrayList<ArrayList<Integer>> tracks = new ArrayList<ArrayList<Integer>>();
				ArrayList<Integer> addedNodes = new ArrayList<Integer>();
				for (int i = 0; i < myTracks.length(); i++)
				{
					if (!addedNodes.contains(i))
					{
						ArrayList<Integer> toAdd = new ArrayList<Integer>();
						toAdd.add(i);
						ArrayList<Integer> thisTrack = new ArrayList<Integer>();
						while (toAdd.size() > 0)
						{
							if (!thisTrack.contains(toAdd.get(0)))
							{
								int thisVal = toAdd.get(0);
								thisTrack.add(thisVal);
								for (int j = 0; j < myTracks.length(); j++)
								{
									if (myTracks.getBoolean(thisVal, j) || myTracks.getBoolean(j, thisVal))
										toAdd.add(j);
								}
							}
							toAdd.remove(0);
						}
						addedNodes.addAll(thisTrack);
						tracks.add(thisTrack);
					}
				}
				for (int i = 0; i < tracks.size(); i++)
				{
					for (int j = 0; j < tracks.get(i).size(); j++)
					{
						for (int k = 0; k < tracks.get(i).size(); k++)
						{
							if (j != k)
								myTracks.set(true, tracks.get(i).get(j), tracks.get(i).get(k));
						}
					}
				}
		        File file = new File(myDirName + "/" + TRACKED_DATA_FILENAME);
		        
		        Writer output = null;
		        output = new BufferedWriter(new FileWriter(file));
		        output.flush();
		        
		        output.write("" + myFrameRate + "\n");
		        
		        int frame = 1;
		        int lastOb = 0;
		        
	        	String toWrite = "Rectangle 0 0.0 0.0 1.0 1.0 255 255 255\n";
	        	output.write(toWrite);

		        while (true)
		        {
		        	HashMap<Integer, ArrayList<String>> stringsToWrite = new HashMap<Integer, ArrayList<String>>();
		        	ArrayList<String> colorStrings = new ArrayList<String>();
		        	for (int i = 0; i < myWeights.length(); i++)
			        {
			        	for (int j = i; j < myWeights.length(); j++)
			        	{
			        		if (myWeights.get(i, j) > 0.0 || (myObservations.get(i).id == myObservations.get(j).id && myObservations.get(i).frameNum == myObservations.get(j).frameNum - 1))
			        		{
			        			boolean idsMatch = myObservations.get(i).id == myObservations.get(j).id;
			        			boolean isTracked = myTracks.getBoolean(i, j);
			        			int width = (int)(myWeights.get(i, j) / 0.2) + 1;
			        			double xStart = myObservations.get(i).x;
			        			double zStart = myObservations.get(i).z;
			        			double xEnd = myObservations.get(j).x;
			        			double zEnd = myObservations.get(j).z;
			        			int frameDiff = Math.min(Math.abs(frame - myObservations.get(i).frameNum), Math.abs(frame - myObservations.get(j).frameNum));
			        			int colorVal = (frameDiff < Data.weightFrames)?(Data.weightFrames - frameDiff):0;
			        			double colorMult = ((double)colorVal)/Data.weightFrames;
			        			toWrite = "Line " + frame + " " + xStart + " " + zStart + " " + xEnd + " " + zEnd;
			        			int greyScale = (int)(255 - 255 * colorMult);
			        			String color = isTracked?" 255 "+ greyScale + " "+ greyScale:" " + greyScale + " " + greyScale + " " + greyScale;
			        			if (!isTracked && idsMatch)
			        				color = " " + greyScale + " " + greyScale + " 255";
			        			if (isTracked && !idsMatch)
			        				color = " " + greyScale + " 255 " + greyScale;
			        			toWrite += color + " " + width + "\n";
			        			if (colorMult > 0.05)
			        			{
			        				if (!stringsToWrite.containsKey(colorVal))
			        					stringsToWrite.put(colorVal, new ArrayList<String>());
			        				stringsToWrite.get(colorVal).add(toWrite);
			        				if (isTracked || idsMatch)
			        					colorStrings.add(toWrite);
			        			}
			        		}
			        	}
			        }
			        for (int i = 1; i <= Data.weightFrames; i++)
			        {
			        	if (stringsToWrite.containsKey(i))
			        	{
				        	ArrayList<String> edges = stringsToWrite.get(i);
				        	for (int j = 0; j < edges.size(); j++)
				        		output.write(edges.get(j));
			        	}
			        }
			        for (int i = 0; i < colorStrings.size(); i++)
			        	output.write(colorStrings.get(i));
			        for (int i = lastOb; i < myObservations.size(); i++)
			        {
			        	if (myObservations.get(i).frameNum != frame)
			        	{
			        		frame++;
			        		break;
			        	}
			        	lastOb++;
			        	toWrite = "Observation " + frame + " " + myObservations.get(i).x + " " + myObservations.get(i).z + " ";
			        	for (int j = 0; j < myObservations.get(i).attributes.length; j++)
			        	{
			        		toWrite += myObservations.get(i).attributes[j] + " ";
			        	}
			        	toWrite += myObservations.get(i).id + "\n";
				        //output.write(toWrite);
			        }
			        if (lastOb == myObservations.size())
			        	break;
		        }
		        
		        output.close();
			}
			catch (Exception e)
			{
				System.out.println("Problem creating file.");
				e.printStackTrace();
			}
		}
	}
}
